package cc.opcol.iot.server.server;

import cc.opcol.iot.server.parser.SessionEventHandle;
import cc.opcol.iot.server.util.ThreadUtil;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SessionManager {
    private static Map<String,IoTSession> sessions=new ConcurrentHashMap<>();
    private static Map<String,List<SessionEventHandle>> devTypeDataParserMaps=new ConcurrentHashMap<>();
    private static List<SessionEventHandle> normalParsers=new ArrayList<>();
    private static ConcurrentHashMap<String,IoTSession> bizSessions=new ConcurrentHashMap<>();

    public static void put(IoTSession session){
        IoTSession oldSession=sessions.get(session.getId());
        if(oldSession!=null){
            remove(session);
        }
        session.addAllEventHandles(filterParsers(session));
        sessions.put(session.getId(),session);
        session.onActive();
    }

    private static List<SessionEventHandle> filterParsers(IoTSession session) {
        List<SessionEventHandle> parsers=new ArrayList<>();
        if(!StringUtils.isBlank(session.getDeviceType()) && devTypeDataParserMaps.get(session.getDeviceType())!=null){
            parsers.addAll(devTypeDataParserMaps.get(session.getDeviceType()));
        }
        parsers.addAll(normalParsers);
        return parsers;
    }

    public static void addSessionEventHandle(String type, SessionEventHandle sessionEventHandle){
        if(StringUtils.isBlank(type)){
            normalParsers.add(sessionEventHandle);
        }else {
            List<SessionEventHandle> sessionEventHandles =devTypeDataParserMaps.get(type);
            if(sessionEventHandles ==null){
                sessionEventHandles =new ArrayList<>();
                devTypeDataParserMaps.put(type, sessionEventHandles);
            }
            sessionEventHandles.add(sessionEventHandle);
        }
        ThreadUtil.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                for(String key: sessions.keySet()){
                    IoTSession session=sessions.get(key);
                    session.addEventHandle(sessionEventHandle);
                }
            }
        });
    }

    public static void onSessionLogin(IoTSession session) {
        String loginDeviceId=(String) session.getCache().get("dev_id");
        if(loginDeviceId==null){
            return;
        }
        IoTSession removeSession=null;
        for(String key:sessions.keySet()){
            IoTSession os=sessions.get(key);
            if(os.getId().equals(session.getId())){
                continue;
            }
            String devId= (String) os.getCache().get("dev_id");
            if(devId==null){
                continue;
            }
            if(devId.equals(loginDeviceId)){
                removeSession=os;
                break;
            }
        }
        if(removeSession!=null){
            sessions.remove(removeSession.getId());
            removeSession.getCtx().close();
        }
        bizSessions.put(loginDeviceId,session);
    }

    public static IoTSession getTopOne() {
        if(bizSessions.size()>0){
            Object objects[] =  bizSessions.keySet().toArray();
            return bizSessions.get(objects[objects.length-1]);
        }
        return null;
    }

    public void removeSessionEventHandle(String type, SessionEventHandle sessionEventHandle){
        if(StringUtils.isBlank(type)){
            normalParsers.remove(sessionEventHandle);
        }else {
            List<SessionEventHandle> sessionEventHandles =devTypeDataParserMaps.get(type);
            if(sessionEventHandles ==null){
                return;
            }
            for(SessionEventHandle sessionEventHandleOO : sessionEventHandles){
                if(sessionEventHandleOO.equals(sessionEventHandle)){
                    sessionEventHandles.remove(sessionEventHandleOO);
                    break;
                }
            }

            for(String key: sessions.keySet()){
                IoTSession session=sessions.get(key);
                session.removeEventHandle(sessionEventHandle);
            }
        }
    }


    public static void remove(IoTSession session){
        session.getCtx().close();
        session.onInActive();
        String loginDeviceId=(String) session.getCache().get("dev_id");
        if(loginDeviceId==null){
            return;
        }
        bizSessions.remove(loginDeviceId,session);
    }

    public static IoTSession get(String id) {
        return sessions.get(id);
    }

    public static IoTSession getByBizId(String id){
        return bizSessions.get(id);
    }
}
